#include "LUNA_VorbisSystem.h"

#include "al.h"
#include "Vorbis\vorbisfile.h"

using namespace LUNA;

VorbisSystem::VorbisSystem() :
vorbisDLLHandle( 0 ),
fn_ov_clear( 0 ),
fn_ov_read( 0 ),
fn_ov_pcm_total( 0 ),
fn_ov_info( 0 ),
fn_ov_comment( 0 ),
fn_ov_open_callbacks( 0 )
{
	vorbisCallbacks.read_func = &VorbisSystem::read;
	vorbisCallbacks.seek_func = &VorbisSystem::seek;
	vorbisCallbacks.close_func = &VorbisSystem::close;
	vorbisCallbacks.tell_func = &VorbisSystem::tell;
}

size_t VorbisSystem::read( void *ptr, size_t size, size_t nmemb, void *datasource )
{
	return fread(ptr, size, nmemb, (FILE*)datasource);
}

int VorbisSystem::seek( void *datasource, ogg_int64_t offset, int whence )
{
	return fseek((FILE*)datasource, (long)offset, whence);
}

int VorbisSystem::close( void *datasource )
{
   return fclose((FILE*)datasource);
}

long VorbisSystem::tell( void *datasource )
{
	return ftell((FILE*)datasource);
}

void VorbisSystem::swap( short &s1, short &s2 )
{
	short temp = s1;
	s1 = s2;
	s2 = temp;
}

unsigned long VorbisSystem::decodeOggVorbis( OggVorbis_File *oggVorbisFile,
	char *decodeBuffer, unsigned long bufferSize, unsigned long channels )
{
	int currentSection = 0;
	long decodeSize = 0;
	unsigned long numSamples = 0;
	short *samples = 0;

	unsigned long bytesDone = 0;
	while( true )
	{
		decodeSize = 
			fn_ov_read( 
				oggVorbisFile,
				decodeBuffer + bytesDone,
				bufferSize - bytesDone, 
				0, 2, 1, 
				&currentSection 
				);

		if( decodeSize > 0 )
		{
			bytesDone += decodeSize;

			if( bytesDone >= bufferSize )
				break;
		}
		else
		{
			break;
		}
	}

	if( channels == 6 )
	{
		samples = (short*)decodeBuffer;
		for( numSamples = 0; numSamples < (bufferSize>>1); numSamples += 6 )
		{
			swap(samples[numSamples+1], samples[numSamples+2]);
			swap(samples[numSamples+3], samples[numSamples+4]);
			swap(samples[numSamples+5], samples[numSamples+6]);
		}
	}

	return bytesDone;
}